package vm


// for循环相关指令


import "api"


// FORREP指令
// R(A) -= R(A+2); pc += sBx
func forPrep(i Instruction, vm api.LuaVM) {

	a, sBx := i.AsBx()
	a += 1

	// R(A) -= R(A+2)
	vm.PushValue(a)
	vm.PushValue(a+2)
	vm.Arith(api.LUA_OPSUB)
	vm.Replace(a)

	// pc += sBx
	vm.AddPC(sBx)
}


// FORLOOP指令
// R(A) += R(A+2)
// if R(A) <?= R(A+1) then {
//    pc += sBx; R(A+3) = R(A)
// }
func forLoop(i Instruction, vm api.LuaVM) {

	a, sBx := i.AsBx()
	a += 1

	// R(A) += R(A+2)
	vm.PushValue(a + 2)
	vm.PushValue(a)
	vm.Arith(api.LUA_OPADD)
	vm.Replace(a)

	// R(A) <?= R(A+1)
	isPositiveStep := vm.ToNumber(a+2) >= 0
	if (isPositiveStep && vm.Compare(a, a+1, api.LUA_OPLE)) || 
		(!isPositiveStep && vm.Compare(a+1, a, api.LUA_OPLE)) {

		vm.AddPC(sBx)  // pc += sBx
		vm.Copy(a, a+3)  // R(A+3) = R(A) // 局部变量i
	}
}


// `TFORLOOP`指令(`iAsBx`模式)
// if R(A+1) ~= nil then {
//     R(A) = R(A+1); pc += sBx
// }
func tForLoop(i Instruction, vm api.LuaVM) {

	a, sBx := i.AsBx()
	a += 1

	if !vm.IsNil(a+1) {

		vm.Copy(a+1, a)
		vm.AddPC(sBx)
	}
}